package day13;

import java.util.Date;

/*
 * 面向对象特征三 多态性
 * 
 * 理解多态性：可以理解为一个事物的多种形态
 * 
 * 1.理解多态性，可以理解为一个事物的多种形态。
 * 2.何为多态性：
 * 		对象的多态性：父类引用指向子类的对象(或子类对象赋给父类的引用)
 * 3. 多态的使用，虚拟方法调用
 * 		有了对象的多态性以后，我们在编译期，只能调用父类中声明的方法，但运行期，我们实际执行的是子类重写父类的方法、
 * 		总结： 编译，看左边，运行，看右边。
 * 
 * 4.多态性的使用前提：① 继承的多态性  ② 方法的重写
 * 
 * 5.对象的多态性，只使用与方法，不适用于属性（编译和运行都看左边）
 * 
 *****************************
 * 
 * 
 * 
 */
public class PersonTest2 {
	public static void main(String[] args) {
		Person p1 = new Person();
		p1.eat();
		Man man = new Man();
		man.eat();
		man.age = 25;
		man.earnMoney();
		System.out.println("******************************");
		// 对象多态性，父类的引用指向子类的对象
		Person p2 = new Man();
//		Person p3 = new Woman();
		// 多态的使用，当调用子父类同名同参数的方法时，实际执行的是子类重写父类的方法 --- 虚拟方法调用
		p2.eat();
		p2.walk();
		
		// 无法调用子类特有的
		p2.name = "tom";
//		p2.earnMoney();
		
		System.out.println("*****************");
		
		// 有了对象的多态性以后，内存中实际上是加载了子类持有的属性和方法的，但是由于变量声明为父类类型，
		// 导致编译时，只能调用父类中声明的属性和方法。子类是由的属性和方法不能调用。
		
		// 如何才能调用子类持有的属性和方法。
		// 强制类型转换
		Man m1 = (Man) p2;
		m1.earnMoney();
		m1.isSmoking = true;
		
		// 使用强转的化，可能出现ClassCastException的异常
//		Woman w1 = (Woman)p2;
//		w1.goShopping();
		
		System.out.println("*******************");

		/*
		 * instanceof  关键字使用
		 * 
		 * a instanof A:判断对象a是否是类A的实例。如果是，返回true，如果不是，返回true
		 * 
		 *  使用情境，为了避免在向下转型时出现ClassCastException的异常，我们在向下转型之前，
		 *  先进行instanceof的判断，一旦返回true，就进行向下转型，如果返回false，不进行向下转型。
		 *  
		 *  如果 a instanceof A 返回true，那么 a instanceof B 也为 true
		 *  其中B是A的弗雷
		 *  
		 */
		if (p2 instanceof Woman) {
			Woman w1 = (Woman)p2;
			w1.goShopping();
			System.out.println("*****Woman*****");
		}
		if (p2 instanceof Man) {
			Man m2 = (Man)p2;
			m2.earnMoney();
			System.out.println("*****Man*****");
		}
		if (p2 instanceof Person) {
			System.out.println("*****Person***");
		}
		if (p2 instanceof Object) {
			System.out.println("*****Object***");
		}
		
		
		//问题一  编译通过，运行不通过
		// 举例一
//		Person p3 = new Woman();
//		Man m3 = (Man) p3;
		
		//举例二
//		Person p4 = new Person();
//		Man m4 = (Man)p4;
	
		// 问题二 编译通过， 运行也通过
		Object obj = new Woman();
		Person p = (Person)obj;
		
		// 问题三 编译不通过
//		Man m5 = new Woman();
		
//		String str = new Date();
//		Object o = new Date();
//		String str1 = (String) o;
		
	}

}
